<template>
  <div>
    <el-dialog
      title="发放勋章"
      :visible="isshow"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      width="900px"
      append-to-body
      @close="cancel()"
      destroy-on-close
    >
      <div class="flexbet">
        <el-card class="box-card">
          <div slot="header" class="clearfix">
            <span>接收人</span>
          </div>
          <div class="sea_bar">
            <div>关键词</div>
            <el-input
              placeholder="输入关键字进行过滤"
              v-model="filterText"
              style="width: 180px"
            >
            </el-input>
            <el-button type="primary" size="mini" @click="seaTree"
              >搜索</el-button
            >
          </div>

          <div
            style="
              height: 400px;
              overflow-y: scroll;
              padding: 20px 0px;
              box-sizing: border-box;
            "
          >
            <el-checkbox v-model="checkAll" @change="checkFull">
              全选（{{ this.allStaffData.length }}）
            </el-checkbox>
            <el-tree
              v-loading="Loading"
              show-checkbox
              class="filter-tree"
              :data="data"
              :props="defaultProps"
              :filter-node-method="filterNode"
              ref="tree"
              @check="handleNodeCheck"
              node-key="sid"
            >
            </el-tree>
          </div>
        </el-card>
        <el-card class="box-card">
          <div slot="header" class="clearfix">
            <span>本次发放员工</span>
          </div>
          <div class="sea_bar">
            <el-input
              clearable
              placeholder="输入关键字进行过滤"
              v-model="filterText1"
              style="width: 230px"
              @clear="seaChecked"
              @input="seaChecked"
            >
            </el-input>
            <el-button type="primary" size="mini" @click="seaChecked"
              >搜索</el-button
            >
          </div>
          <div
            style="
              height: 400px;
              overflow-y: scroll;
              padding: 20px 0px;
              box-sizing: border-box;
            "
          >
            <el-card
              class="user-card"
              v-for="(item, index) in filterSelectedData"
              :key="index"
            >
              <div class="flexbet">
                <div>{{ item.name }}</div>
                <i
                  @click="deleteUser(item)"
                  class="el-icon-delete shou"
                  style="margin-top: 2px"
                ></i>
              </div>
            </el-card>
          </div>
        </el-card>
      </div>
      <div
        slot="footer"
        class="dialog-footer"
        style="display: flex; justify-content: flex-end"
      >
        <el-button v-preventReClick @click="cancel">取 消</el-button>
        <el-button
          v-preventReClick
          :loading="submitLoading"
          type="primary"
          @click="submitForm"
        >
          确 认
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import {
  getSendstaffList,
  sendMedal,
  getmedalstaffList,
} from "@/api/medal/medal";
export default {
  props: {
    open: Boolean,
  },
  data() {
    return {
      submitLoading: false,
      checkAll: false,
      isshow: false,
      filterText: "",
      filterText1: "",
      data: [],
      dataChildrens: [],
      defaultProps: {
        children: "list",
        label: "name",
      },
      //禁用的数据
      disabled_selectedData: [],
      // 所有员工数据
      allStaffData: [],
      //选中的原始数据
      selectedData: [],
      // 筛选后的数据
      filterSelectedData: [],
      row: {},
      Loading: true,
      search: "",
    };
  },
  watch: {
    filterText(val) {
      this.search = val;
      this.getTreeList();
    },
  },
  mounted() {},
  methods: {
    show(row) {
      this.row = row;
      this.isshow = true;
      this.Loading = true;
      this.filterText = "";
      this.getTreeList();
    },
    formatData(arr, pidArr = []) {
      arr.forEach((e) => {
        if (pidArr.length === 3) {
          //TODO 根据真实数据的数组层级去改变
          e.sid = `${pidArr[0]}_${pidArr[1]}_${pidArr[2]}_${e.id}`;
          // 获取所有员工
          this.allStaffData.push(e);
        } else {
          e.sid = e.id;
        }
        if (e.list && e.list.length > 0) {
          this.formatData(e.list, [...pidArr, e.id]);
        }
      });
    },
    // 判断某10个数组是否在某60个数组中
    isArraySubset(smallArray, bigArray) {
      for (let i = 0; i < smallArray.length; i++) {
        if (smallArray[i].disabled) {
          continue; // 如果对象有 disabled 属性且为 true，则跳过该对象
        }

        let found = false;
        for (let j = 0; j < bigArray.length; j++) {
          if (smallArray[i].sid === bigArray[j].sid) {
            found = true;
            break;
          }
        }
        if (!found) {
          return false;
        }
      }
      return true;
    },
    // 获取树状结构并处理禁用
    async getTreeList() {
      this.Loading = true;
      // 获取树状
      let res = await getSendstaffList({ search: this.search });
      this.Loading = false;
      this.checkAll = false;
      this.data = res.data;
      // 添加sid,获取所有子集
      this.allStaffData = [];
      this.formatData(this.data);
      // 展开全部
      this.$nextTick(() => {
        this.expandAllNodes(this.$refs.tree.store.root);
      });

      // 获取已发放用户
      let result = await getmedalstaffList(this.row.medalId);
      this.disabled_selectedData = result.data;
      // 处理禁用
      this.$nextTick(() => {
        this.disableNodesByIds(
          this.data,
          this.disabled_selectedData.map((item) => {
            return item.id;
          }),
          this.selectedData
        );
        // 处理上一次的选中
        if (this.selectedData.length > 0) {
          this.selectedData.map((item) => {
            console.log(item);
            this.$refs.tree.setChecked(item.sid, true);
          });
        }
      });

      // 判断是否全选
      this.checkAll = this.isArraySubset(this.allStaffData, this.selectedData);
    },
    checkFull() {
      if (this.checkAll) {
        let arr = [];
        this.data.forEach((e) => {
          arr = [...arr, ...this.getAllLeafNodes(e)];
        });
        arr.map((item) => {
          if (!item.disabled) {
            this.$refs.tree.setChecked(item.sid, true);
          }
        });
        this.data.forEach((e) => {
          this.handleNodeCheck(e);
        });
      } else {
        let arr = [];
        this.data.forEach((e) => {
          arr = [...arr, ...this.getAllLeafNodes(e)];
        });
        arr.map((item) => {
          if (!item.disabled) {
            this.$refs.tree.setChecked(item.sid, false);
          }
        });
        this.data.forEach((e) => {
          this.handleNodeCheck(e);
        });
      }
    },
    /* 递归地在树形结构中 勾选上已禁用和 勾选上右边列表存在的人 */
    /* tree树的数据, idsToDisable禁用的数据 */
    disableNodesByIds(tree, idsToDisable) {
      for (let node of tree) {
        if (idsToDisable.includes(node.id)) {
          this.$set(node, "disabled", true);
          this.$refs.tree.setChecked(node.sid, true);
        }
        if (node.list) {
          this.disableNodesByIds(node.list, idsToDisable); // 递归调用以处理子节点
        }
      }
    },
    /* 删除用户 */
    deleteUser(item) {
      this.sameDeal(item, false);
      this.handleNodeCheck(item);
    },
    /* 递归函数，用于获取某个节点的所 有最子节点 */
    getAllLeafNodes(node, result = []) {
      if (node.list) {
        node.list.forEach((child) => {
          this.getAllLeafNodes(child, result);
        });
      } else {
        // 排除禁用节点
        if (!node.disabled) {
          result.push(node);
        }
      }
      return result;
    },
    /* 判断节点点击是否被选中 */
    isNodeChecked(checkedNode) {
      return this.$refs.tree.getCheckedNodes().some((item) => {
        return item.sid === checkedNode.sid;
      });
    },
    /* 节点点击后 想同的元素要被同时勾选或者 同时不勾选 */
    sameDeal(checkedNode, boolean) {
      this.allStaffData.map((item) => {
        if (item.id == checkedNode.id && !item.disabled) {
          this.$refs.tree.setChecked(item.sid, boolean);
        }
      });
    },
    /* 节点点击 */
    handleNodeCheck(checkedNode) {
      console.log("节点点击", checkedNode, this.isNodeChecked(checkedNode));
      //如果选中的不是员工
      if (checkedNode.list) {
        // 递归函数，用于获取某个节点的所有最子节点
        const AllLeafNodes = this.getAllLeafNodes(checkedNode);
        // 如果节点选中，则所有的子节点都进入selectData中
        if (this.isNodeChecked(checkedNode)) {
          let objectArray = [...AllLeafNodes, ...this.selectedData];
          // 遍历元素所有节点 勾选上节点相同的节点
          AllLeafNodes.map((item) => {
            this.sameDeal(item, true);
          });
          // 通过sid去重
          this.selectedData = Object.values(
            objectArray.reduce((uniqueMap, obj) => {
              uniqueMap[obj.sid] = obj;
              return uniqueMap;
            }, {})
          );
        }
        // 如果节点没有选中，则删除selectData中存在的元素
        else {
          // 原始数组
          let originalArray = this.selectedData;
          // 要删除的数组
          let toRemoveArray = AllLeafNodes;
          AllLeafNodes.map((item) => {
            this.sameDeal(item, false);
          });
          // 根据 toRemoveArray 中的 id 属性值过滤掉 originalArray 中对应的对象
          let filteredArray = originalArray.filter(
            (obj) => !toRemoveArray.some((item) => item.id === obj.id)
          );
          this.selectedData = filteredArray;
        }
      }
      //如果选中的是员工
      else {
        // 如果节点选中，则子节点都进入selectData中
        if (this.isNodeChecked(checkedNode)) {
          // 相同的也要被勾选
          this.allStaffData.map((item) => {
            if (item.id == checkedNode.id && !item.disabled) {
              this.selectedData.unshift(item);
              this.$refs.tree.setChecked(item.sid, true);
            }
          });
        }
        // 如果节点没有选中，则删除selectData中存在的元素
        else {
          this.sameDeal(checkedNode, false);
          // 判断节点的id是否存在selectData中，存在则删除selectData中的该元素
          // 想同的也需要被删除
          if (this.selectedData.some((item) => item.id === checkedNode.id)) {
            this.selectedData = this.selectedData.filter(
              (item) => item.id !== checkedNode.id
            );
          }
        }
      }
      // 最后需要通过id去重后在显示
      this.filterSelectedData = Object.values(
        this.selectedData.reduce((uniqueMap, obj) => {
          uniqueMap[obj.id] = obj;
          return uniqueMap;
        }, {})
      );
      // 是否全选,获取this.$refs.tree.getCheckedNodes()中含_的数据
      this.$nextTick(() => {
        this.checkAll =
          this.$refs.tree
            .getCheckedNodes()
            .filter(
              (obj) =>
                obj.sid &&
                typeof obj.sid === "string" &&
                obj.sid.indexOf("_") !== -1
            ).length === this.allStaffData.length;
      });
    },

    //   过滤
    filterNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    },
    /** 提交按钮 */
    submitForm: function () {
      if (this.selectedData.length === 0) {
        this.$confirm(`本次发放未勾选员工，无法发放！`, "发放提示", {
          showCancelButton: false,
          confirmButtonText: "关闭",
          type: "warning",
        });
        return;
      }
      let arr = this.selectedData.map((i) => i.id);
      let uniqueArray = Array.from(new Set(arr));
      // TODO:调接口传递数据
      const loading = this.$loading({
        lock: true,
        text: "正在发放...",
        spinner: "el-icon-loading",
        background: "rgba(255, 255, 255, 0.6)",
      });
      sendMedal(this.row.medalId, uniqueArray)
        .then((res) => {
          this.isshow = false;
          this.$emit("Sendsuccess");
        })
        .finally(() => loading.close());
    },
    // 表单重置
    reset() {
      this.selectedData = [];
      this.filterSelectedData = [];
      this.data = [];
      this.checkAll = false;
    },
    cancel() {
      this.reset();
      this.isshow = false;
    },
    // 搜索树状
    seaTree() {
      this.$refs.tree.filter(this.filterText);
    },
    // 搜索已选择
    seaChecked() {
      // TODO:搜索另一个数组
      var pattern = new RegExp(this.filterText1, "i"); // 创建一个大小写不敏感的正则表达式模式
      var result = this.selectedData.filter(function (item) {
        return pattern.test(item.name); // 使用正则表达式测试每个项是否与关键字匹配
      });
      this.filterSelectedData = result;
    },
    expandAllNodes(node) {
      if (node) {
        node.expanded = true;
        if (node.childNodes) {
          node.childNodes.forEach((childNode) => {
            this.expandAllNodes(childNode);
          });
        }
      }
    },
  },
};
</script>
<style scoped lang="scss">
::v-deep .user-card .el-card__body {
  padding: 10px;
}
.box-card {
  width: 400px;
  height: 500px;
  // overflow-y: hidden;
}
.sea_bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
::v-deep .el-input--medium .el-input__inner {
  height: 30px;
}
</style>
  